﻿using System;
using System.Collections.Generic;
using GameLogic.Statistics;

namespace GameLogic.Poker
{
    public delegate void myDel();
    public class PokerGame
    {

        public event myDel ChangeRound;
        public List<PokerPlayer> Players; //hashtable?
        public PokerPlayer Desk;
        public PokerPlayer MainPlayer;
        public PokerBot BotPlayer;
        private ICardDeck cardDeck;
        public Currency MinBet { get; private set; }
        public PokerPlayer Winner { get; private set; }
        public GameState gameState;
    	public Currency MinBlind { get; set; }

        public PokerGame()
        {
			Init();
        }
        public PokerGame(PokerPlayer oldBot, PokerPlayer oldPlayer)
        {
			Init();	

            MainPlayer.Money = oldPlayer.Money;
            MainPlayer.User = oldPlayer.User;

            BotPlayer.Money = oldBot.Money;
            BotPlayer.User = oldBot.User;
		}
		public void Init()
		{
			gameState = GameState.Preflop;
            cardDeck = new CardDeck();
			Players = new List<PokerPlayer>();
			Desk = new PokerPlayer(GetCards(5));
			MainPlayer = new PokerPlayer(GetCards(2));
			MainPlayer.ShowAllCards();
			MinBet = new Currency();
			//Обнуляю счет стола вначале раунда. Аня Б.
			Desk.Money.Clear();

			BotPlayer = new PokerBot(GetCards(2));
			Winner = null;
			MinBlind = new Currency(2, 0);
			MinBet = new Currency(MinBlind);
		}
        public void CreatePlayer()
        {
            var playerCards = GetCards(2);
            Players.Add(new PokerPlayer(playerCards) {RoundHistory = {Pocket = playerCards.ToArray()}});
        }

        private List<Card> GetCards(int size)
        {
            var cards = new List<Card>();
            for (int i = 0; i < size; i++)
            {
                cards.Add(cardDeck.GetNextCard());
            }
            return cards;
        }

        public void NextRound()
        {
            cardDeck.Shuffle();
            foreach (var pokerPlayer in Players)
            {
                var playerCards = GetCards(2);
                pokerPlayer.RoundHistory.Pocket = playerCards.ToArray();
                pokerPlayer.Cards = playerCards;
            }
            Desk.Cards = GetCards(5);
        }
       
        //Для удобства взаимодействия интерфейса с логикой новый метод сделала. Аня Б.
        public bool UpdateBet(PokerPlayer player, Currency bet)
        {
            //player.Bet.Add(bet,0);
            //player.Money.Sub(bet, 0);
            //this.Desk.Money.Add(bet, 0);
            player.Bet += bet;
        	player.Money -= bet;
        	Desk.Money += bet;
            if (MinBet <= player.Bet)
            {
               player.RoundHistory.ListBet.Add(MinBet == player.Bet
                                                   ? new Bet(BetName.Call, gameState, bet)
                                                   : new Bet(BetName.Raise, gameState, bet));

                MinBet = player.Bet;
            	BotPlayer.Bet = BotPlayer.GetBet(MinBet);
                if (BotPlayer.Bet == null)
                {
                    Winner = player;
                    player.RoundHistory.BattleResult = BattleResult.Win;  
                }
                else
                {
                    BotPlayer.Money -= BotPlayer.Bet;
                    Desk.Money += BotPlayer.Bet;
                    //BotPlayer.Money.Sub(bet, 0);
                    //Desk.Money.Add(bet, 0);
                }
                return true;
            }
            return false;
        }

       public void GoToNextTradeRound()
        {
            ++gameState;
            Players.ForEach(pokerPlayer => pokerPlayer.RoundHistory.FinalStreet = gameState);
           //При новом круге торгов минимальная ставка и ставки игроков должны обнуляться. Аня Б.
            //MinBet.Clear();
		    MinBet = new Currency(MinBlind);
            MainPlayer.Bet.Clear();
            BotPlayer.Bet.Clear();

            switch (gameState)
            {
                case GameState.Flop:
                    {
                        for (int i = 0; i < 3; i++)
                            Desk.Cards[i].State = State.Up;
                        break;
                    }
                case GameState.Turn:
                    {
                        Desk.Cards[3].State = State.Up;
                        break;
                    }
                case GameState.River: 
                    {
                        Desk.Cards[4].State = State.Up;
                        break;
                    }
                case GameState.ShowDown:
                    {
                        foreach(Card card in MainPlayer.Cards)
                            card.State = State.Up;
                        foreach(Card card in BotPlayer.Cards)
                            card.State = State.Up;
                    	foreach (var card in Desk.Cards)
                    		card.State = State.Up;
                        CheckForWinner();
                        break;
                    }
            }
            if (ChangeRound != null)
            {
                ChangeRound();
            }
        }

        private void CheckForWinner()
        {
            var handGenerator = new HandGenerator(new CombinationGenerator());
            var handComparer = new HandComparer();
            var playerHands = handGenerator.GenerateFromTwoFive(MainPlayer.Cards, Desk.Cards);
            var botHands = handGenerator.GenerateFromTwoFive(BotPlayer.Cards, Desk.Cards);
            var bestPlayerHand = handComparer.FindTheBestHand(playerHands);
            var bestBotHand = handComparer.FindTheBestHand(botHands);
            var bestHand = handComparer.FindTheBestHand(new Hand[] {bestPlayerHand, bestBotHand});
            MainPlayer.RoundHistory.Hend = bestPlayerHand.HandRang;
            if (Equals(bestHand, bestPlayerHand))
            {
                MainPlayer.RoundHistory.BattleResult = BattleResult.Win;
                Winner = MainPlayer;

            }
            else
            {
                MainPlayer.RoundHistory.BattleResult = BattleResult.Loss;
                Winner = Equals(bestHand, bestBotHand) ? BotPlayer : Desk;
            }
            MainPlayer.PlayerHistory.Add(MainPlayer.RoundHistory);
            MainPlayer.RoundHistory.ListBet.Clear();
        }
    }
}